package com.chen.springboot.service.Impl;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.IdUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chen.springboot.dto.OrderDto;
import com.chen.springboot.entity.Item;
import com.chen.springboot.entity.Order;
import com.chen.springboot.entity.User;
import com.chen.springboot.exception.ServiceException;
import com.chen.springboot.mapper.ItemMapper;
import com.chen.springboot.mapper.OrderMapper;
import com.chen.springboot.mapper.RefundOrderMapper;
import com.chen.springboot.mapper.UserMapper;
import com.chen.springboot.service.OrderService;
import com.chen.springboot.utils.TokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    OrderMapper orderMapper;

    @Autowired
    UserMapper userMapper;

    @Autowired
    ItemMapper itemMapper;

    @Autowired
    RefundOrderMapper refundOrderMapper;

    @Override
    public void save(Order order) {
        orderMapper.insert(order);
    }

    @Override
    public void update(Order order) {
        orderMapper.updateById(order);
    }

    @Override
    public void ship(String orderNo) {
        refundOrderMapper.updateRefundState(4, orderNo);
    }

    @Override
    public void delete(Long id) {
        orderMapper.deleteById(id);
    }

    @Override
    public void deleteAll(List<Long> ids) {
        for (Long id : ids) {
            orderMapper.deleteById(id);
        }
    }

    @Override
    public Order getById(Long id) {
        return orderMapper.selectById(id);
    }

    @Override
    public void buy(Long itemId, Integer userId, Integer count) {
        Item item = itemMapper.selectById(itemId);
        User user = userMapper.selectById(userId);
        String orderNo = IdUtil.getSnowflake().nextIdStr();
        Order order = createOrder(item, user, orderNo, count);
        LocalDateTime now = LocalDateTime.now();
        String payTimeStr = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        orderMapper.updateState(orderNo, 1, payTimeStr);
    }

    @Override
    public void buyCart(List<Order> orders) {
        // 生成订单号
        String orderNo = IdUtil.getSnowflake().nextIdStr();
        // 生成订单名称
        // 对所以加入购物车的商品进行处理，添加订单号
        for (Order order : orders) {
            order.setOrderNo(orderNo);
            // 同时也更新商品的选择数量
            orderMapper.updateById(order);
        }
        LocalDateTime now = LocalDateTime.now();
        String payTimeStr = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        // 更新订单状态为1
        orderMapper.updateState(orderNo, 1, payTimeStr);
    }

    @Override
    public void addToCart(Long itemId, Integer userId, Integer count) {
        Item item = itemMapper.selectById(itemId);
        User user = userMapper.selectById(userId);
        createOrder(item, user, "", count);
    }

    @Override
    public Page<Order> findPage(Integer pageNum, Integer pageSize, String search) {
        //新建分页对象
        Page<Order> page = new Page<>(pageNum, pageSize);
        //新建模糊查询对象,这里有个注意事项，你模糊项查询的对应项不能为null，为null就查不出来
        //LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>lambdaQuery().like(User::getUsername, search);
        LambdaQueryWrapper<Order> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.orderByDesc(Order::getCreateTime);
        if (!search.isEmpty())
            queryWrapper.like(Order::getOrderName, search);
        return orderMapper.selectPage(page, queryWrapper);
    }

    //post获取全部订单分页查询
    @Override
    public Page<Order>findPages(Integer pageNum, Integer pageSize, String orderNo, Integer state,String OrderName){
        Page<Order> page=new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Order> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.orderByDesc( Order::getCreateTime);
        if(StringUtils.hasText(orderNo))
            queryWrapper.eq(Order::getOrderNo, orderNo);
        if(StringUtils.hasText(OrderName))
            queryWrapper.like(Order::getOrderName, OrderName);
        if (state != null)
            queryWrapper.eq(Order::getState, state);

        return orderMapper.selectPage(page, queryWrapper);
    }

    @Override
    public Page<Order> findUserOrder(Integer pageNum, Integer pageSize, String search, Integer state) {
        // 从 token 获取 userID
        String userId = TokenUtils.getCurrUser();
        //新建分页对象
        Page<Order> page = new Page<>(pageNum, pageSize);
        //新建模糊查询对象,这里有个注意事项，你模糊项查询的对应项不能为null，为null就查不出来
        //LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>lambdaQuery().like(User::getUsername, search);
        LambdaQueryWrapper<Order> queryWrapper = Wrappers.lambdaQuery();
        // 给查询对象加上ID限制和日期降序
        queryWrapper.eq(Order::getUserId, userId);
        if (state == 2)
            queryWrapper.orderByDesc(Order::getCreateTime);
        else
            queryWrapper.orderByDesc(Order::getPaymentTime);
        // 不为空就给查询对象加上搜索限制,例如是否查询未支付订单，或者模糊搜索
        if (state != 0)
            queryWrapper.eq(Order::getState, state);
        if (!search.isEmpty())
            queryWrapper.like(Order::getOrderName, search);
        return orderMapper.selectPage(page, queryWrapper);
    }

    @Override
    public List<Order> findOrderByNo(String orderNo) {
        LambdaQueryWrapper<Order> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(Order::getOrderNo, orderNo);
        return orderMapper.selectList(wrapper);
    }

    @Override
    public void receipt(Integer id) {
        // 创建当前时间
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String now = format.format(new Date());
        // 更新订单状态和结束时间
        if (orderMapper.updateReceiptState(id, now) <= 0)
            throw new ServiceException("400", "确认收货出错");
    }

    @Override
    public Dict charts() {
        // 包装折线图的数据
        LambdaQueryWrapper<Order> wrapper = Wrappers.<Order>lambdaQuery().isNotNull(Order::getPaymentTime);
        List<Order> orders = orderMapper.selectList(wrapper);
        // 获取下单的日期，并对日期排序
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        List<String> dateList = orders.stream().map(order -> (format.format(order.getPaymentTime())))
                .distinct().sorted(Comparator.naturalOrder()).collect(Collectors.toList());
        List<Dict> lineList = new ArrayList<>();
        // 获取每天下单的金额和
        for (String date : dateList) {
            // 从 orders 里面找到这一天的订单
            BigDecimal sum = orders.stream().filter(order -> format.format(order.getPaymentTime()).equals(date))
                    .map(order -> order.getPayPrice().multiply(new BigDecimal(order.getCount())))
                    .reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
            Dict dict = Dict.create().set("date", date).set("value", sum);
            lineList.add(dict);
        }

        List<Dict> barList = new ArrayList<>();
        // 包装柱状图的数据，每天的订单量
        for (String date : dateList) {
            Integer numbers = orders.stream().filter(order -> format.format(order.getPaymentTime()).equals(date))
                    // 把每个订单映射成 1
                    .map(order -> 1).reduce(Math::addExact).orElse(0);
            Dict dict = Dict.create().set("date", date).set("count", numbers);
            barList.add(dict);
        }

        return Dict.create().set("lineData", lineList).set("barData", barList);
    }

    @Override
    public void download(HttpServletResponse response) {
        Page<Order> result = findPage(1, Integer.MAX_VALUE, "");
        List<Order> Orders = result.getRecords();

        // 将 Order 对象列表转换为 OrderDto 列表
        List<OrderDto> OrderDtos = Orders.stream()
                .map(OrderDto::new)
                .collect(Collectors.toList());

        //写出文件
        try {
            EasyExcel.write(response.getOutputStream(), OrderDto.class)
                    .sheet()
                    .doWrite(OrderDtos);
        } catch (IOException e) {
            throw new ServiceException("401",e.getMessage());
        }
    }

    //创建订单
    private Order createOrder(Item item, User user, String orderNo, Integer count) {
        Order order = new Order();
        // 设置商品ID
        order.setProductId(item.getId());
        // 获取商品名称
        order.setOrderName(item.getTitle());
        // 设置订单号
        order.setOrderNo(orderNo);
        // 设置订单价格
        order.setPayPrice(item.getPrice());
        // 设置邮费
        order.setPostFee(BigDecimal.ZERO);
        // 设置商品数量
        order.setCount(count);
        // 设置支付状态
        order.setState(2);
        order.setUserId(user.getId());
        order.setUsername(user.getUsername());
        order.setOrderPicture(item.getImage());
        //构建创建时间
        Date currDate = new Date();
        order.setCreateTime(currDate);
        save(order);
        return order;
    }
}

